// Includes
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <limits.h>
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>

//Incluyo la clase Mersenne-Twister para la generación de números aleatorios en C++
#include "utils/mt.h"

//Incluyo la clase Random para la generación de números aleatorios en CUDA
#include "utils/Random.cu"

//Incluyo la clase cuPrintf para poder imprimir desde GPU
#include "utils/cuPrintf.cu"

//Incluyo la clase parser.cpp para obetener los parametros
#include "utils/parser.cpp"

//Incluyo la clase global.cu  que contiene las variables y funciones globales
#include "utils/global.cu"

//Incluyo la clase binaria.cu que implementa los operadores de la representacion binaria
#include "representaciones/binaria.cu"

//Incluyo la clase binaria.cu que implementa los operadores de la representacion entera
#include "representaciones/entera.cu"

//Incluyo la clase binaria.cu que implementa los operadores de la representacion de permutacion
#include "representaciones/permutacion.cu"

//Incluyo la clase binaria.cu que implementa los operadores de la representacion real
#include "representaciones/real.cu"

//Semilla aleatoria a utilizar.
#define SEMILLA (time(NULL))

using namespace std;


//////////////////////
// Program main
//////////////////////

int main( int argc, char** argv) {
	cudaPrintfInit();

	int * parametros = obtenerParametros();
	asignarParametros(parametros);

	dim3 tamGridAsig(1,1); //Grid dimensión
	dim3 tamBlockAsig(1,1,1); //Block dimensión

	int tamVectorParametros = sizeof(int)*18;
	int *parametrosDevice;
	cudaMalloc(&parametrosDevice, tamVectorParametros);

	cudaMemcpy (parametrosDevice, parametros, tamVectorParametros, cudaMemcpyHostToDevice);
	//asignacion de parametros en GPU
	asignarParametrosDevice<<<tamGridAsig, tamBlockAsig>>>(parametrosDevice);

	totalGenes = cantidadPoblaciones * cantCromosomasPoblacion * cantGenesEnCromosoma;
	totalIndividuos = cantCromosomasPoblacion*cantidadPoblaciones;

	if (tipoRepresentacion == 0) {
		representacionBinaria();
	}
	else {
		if (tipoRepresentacion == 1) {
			representacionEntera();
		}else {
			if (tipoRepresentacion == 2) {
				representacionPermutacion();
			}
			else {
				representacionReal();
			}
		}
	}
	cudaPrintfDisplay(stdout, true);
	cudaPrintfEnd();

}
